﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Social.Core.Contracts;
using System.Net;
using System.IO;

namespace Social.Core.Protocols
{
    /// <summary>
    /// Light version of OAuth 2.0.
    /// This implementation allow the authentication flow and the request for secure data
    /// http://tools.ietf.org/html/rfc5849
    /// </summary>
    /// <remarks>
    ///       +--------+                               +---------------+
    ///      |        |--(A)- Authorization Request ->|   Resource    |
    ///      |        |                               |     Owner     |
    ///      |        |<-(B)-- Authorization Grant ---|               |
    ///      |        |                               +---------------+
    ///      |        |
    ///      |        |        Authorization Grant &  +---------------+
    ///      |        |--(C)--- Client Credentials -->| Authorization |
    ///      | Client |                               |     Server    |
    ///      |        |<-(D)----- Access Token -------|               |
    ///      |        |                               +---------------+
    ///      |        |
    ///      |        |                               +---------------+
    ///      |        |--(E)----- Access Token ------>|    Resource   |
    ///      |        |                               |     Server    |
    ///      |        |<-(F)--- Protected Resource ---|               |
    ///      +--------+                               +---------------+    
    /// 
    /// </remarks>
    public class OAuth2_0 : IProtocol
    {
        /// <summary>
        /// Request Url Formatter Implementation
        /// </summary>
        /// <see cref="Social.Core.Contracts.IRequestFormatter"/>
        public IRequestFormatter RequestFormat{ get; set; }

        /// <summary>
        /// Url  to use in the step A of the OAuth protocol
        /// </summary>
        public String AuthorizationRequestUrl { get; set; }


        /// <summary>
        /// Url to use in step C of OAuth protocol
        /// </summary>
        public string ClientCredentialsUrlRequest
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or Sets the HttpApplication object to make Http requests
        /// </summary>
        public  HttpApplication  Context { get; set; }

       


        #region IProtocol implementation
        #region Protocol Flow

       
        /// <summary>
        /// Step A from the OAuth 2.0 protocol
        /// The client requests authorization from the resource owner.  The
        ///authorization request can be made directly to the resource owner
        ///(as shown), or preferably indirectly via an intermediary such as
        ///an authorization server.
        /// </summary>
        /// <param name="objectId"></param>
        /// <param name="args"></param>
        public void AuthorizationRequest(string objectId, AuthorizationRequestArgs args) 
        {
            string url  = string.Empty;
            if (String.IsNullOrWhiteSpace(objectId))
                throw new Exception("it was not possible to identify the framework object to request for authorization");
            else
                url = RequestFormat.FormatUrl(AuthorizationRequestUrl, objectId, args);

            Context.Response.Redirect(url);
        }
        /// <summary>
        /// Step C from the OAuth 2.0 Protocol
        /// The client requests an access token by authenticating with the
        /// authorization server using its client credentials (prearranged
        /// between the client and authorization server) and presenting the
        /// authorization grant.
        /// </summary>
        /// <param name="clientAccessTokenTokenName"> the name to refer the access token </param>
        /// <param name="credentials"></param>
        /// <returns></returns>
        public string ClientCredentialsRequest(string clientAccessTokenTokenName, ClientCredentials credentials) 
        {
           
                 //"oauth/access_token"
            string url = RequestFormat.FormatUrl(ClientCredentialsUrlRequest, clientAccessTokenTokenName, credentials);
            
            string access_token = DoRequest(url);

            return  access_token.Split('=')[1];
        }
        #endregion 


        /// <summary>
        ///  Step E from the OAuth 2.0 Protocol
        ///  The client requests the protected resource from the resource
        ///  server and authenticates by presenting the access token.
        /// </summary>
        /// <param name="url">Destiny request url</param>
        /// <returns>request result</returns>
        public string DoRequest(string url)
        {
            return DoRequest(url, null, null);
        }

        /// <summary>
        ///  Step E from the OAuth 2.0 Protocol
        ///  The client requests the protected resource from the resource
        ///  server and authenticates by presenting the access token.
        /// </summary>
        /// <param name="url">Destiny request url</param>
        ///  /// <param name="method">Http VERB to use</param>
        /// <returns>request result</returns>
        public string DoRequest(string url, string method)
        {
            return DoRequest(url, method, null);
        }

        /// <summary>
        ///  Step E from the OAuth 2.0 Protocol
        ///  The client requests the protected resource from the resource
        ///  server and authenticates by presenting the access token.
        /// </summary>
        /// <param name="url">Destiny request url</param>
      /// <param name="credentials">Request Credentials</param>
        /// <returns>request result</returns>
        public string DoRequest(string url, ICredentials credentials)
        {
            return DoRequest(url, null, credentials);
        }

        /// <summary>
        ///  Step E from the OAuth 2.0 Protocol
        ///  The client requests the protected resource from the resource
        ///  server and authenticates by presenting the access token.
        /// </summary>
        /// <param name="url">Destiny request url</param>
        ///  /// <param name="method">Http VERB to use</param>
        /// <param name="credentials">Request Credentials</param>
        /// <returns>request result</returns>
        public string DoRequest(string url, string method, ICredentials credentials)
        {
            WebRequest req = System.Net.WebRequest.Create(url);

            if (!String.IsNullOrWhiteSpace(method))
                req.Method = method;

            if (credentials != null)
                req.Credentials = credentials;

            WebResponse resp = req.GetResponse();

            Stream dataStream = resp.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string result = reader.ReadToEnd();

            return result;
        }
        #endregion 
    

    }   
}
